﻿using DidaCode.Workflow.Help;
using DidaCode.Workflow.Logs;
using DidaCode.Workflow.Models;
using DidaCode.Workflow.NodeAttribute;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;

namespace DidaCode.Workflow.NodeBase
{
    public interface INode<TInput, TOutput>
    {
        Task<NodeResult<TOutput>> ExecuteAsync(ExecutionContext<TInput, TOutput> context);
        bool ShouldExecute();
        void AddChild(INode<TInput, TOutput> child);
    }




    public abstract class NodeBase<TInput, TOutput> : INode<TInput, TOutput>
    {
        protected readonly string _switchConfig;

        private readonly List<INode<TInput, TOutput>> _children;

        protected NodeBase(string switchConfig)
        {
            _switchConfig = switchConfig;
            _children = new List<INode<TInput, TOutput>>();
        }
        public async Task<NodeResult<TOutput>> ExecuteAsync(ExecutionContext<TInput, TOutput> context)
        {
            var nodeName = NodeFactory.NodeName(GetType());
            try
            {
                if (!ShouldExecute())
                {
                    if (string.IsNullOrEmpty(nodeName))
                    {
                        Console.WriteLine($"节点{nodeName}未找到节点名称");
                    }
                    else
                    {
                        Console.WriteLine($"节点:{nodeName}被忽略执行");
                    }
                    // 如果当前节点不应该执行，直接返回一个失败的结果
                    return NodeResult<TOutput>.FailNode();
                }

                if (context.Input == null)
                {
                    Console.WriteLine($"节点:{nodeName}输入参数为空");
                    return NodeResult<TOutput>.FailNode();
                }
                var nodeType = NodeFactory.NodeType(nodeName);
                ProcessDataStorage.StoreData(context.Input);
                ProcessExecutor.AutoAssignFromStorage(this);
                var result = await ExecuteNodeAsync(context) .ConfigureAwait(false)   ;
                if (!result.IsSuccess)
                {
                    if (!NodeConfig.GetNodeConfig(nodeName).ContinueOnFailure)
                    {
                        Console.WriteLine($"{nodeName}被执行失败，终止执行");
                        return result;
                    }
                    Console.WriteLine($"{nodeName}被执行失败，继续执行");
                }
                ProcessDataStorage.StoreData(this);
                foreach (var child in _children)
                {  
                    var childResult = await child.ExecuteAsync(context).ConfigureAwait(false);
                }
                return result;
            }
            catch (Exception)
            {
                throw new InvalidOperationException($"Child node :{nodeName} type mismatch");
            }
        }

        public virtual bool ShouldExecute()
        {
            return string.IsNullOrEmpty(_switchConfig) || string.Equals(_switchConfig, "true", StringComparison.OrdinalIgnoreCase);
        }

        public void AddChild(INode<TInput, TOutput> child)
        {
            _children.Add(child);
        }





        protected abstract Task<NodeResult<TOutput>> ExecuteNodeAsync(ExecutionContext<TInput, TOutput> context);


        // 自动为节点赋值输入参数
        private void AutoAssignInput<TInput, TOutput>(TInput input, TOutput output)
        {
            var nodeType = this.GetType();
            foreach (var property in nodeType.GetProperties())
            {
                var mappingName = GetMappingName(property);
                if (mappingName == null) continue;

                // 从输入或输出对象中查找匹配的属性
                var inputProperty = input.GetType().GetProperties().FirstOrDefault(s => GetMappingName(s) == mappingName);
                var outputProperty = output.GetType().GetProperties().FirstOrDefault(s => GetMappingName(s) == mappingName);

                object value = inputProperty?.GetValue(input) ?? outputProperty?.GetValue(output);
                if (value != null && property.CanWrite)
                {
                    property.SetValue(this, value);
                }
            }
        }

        // 自动将节点的输出赋值到流程输出对象
        private void AutoAssignOutput<TOutput>(TOutput output)
        {
            var nodeType = this.GetType();
            var nodePropertyDic = new Dictionary<string, object>();
            foreach (var property in nodeType.GetProperties())
            {
                var mappingName = GetMappingName(property);
                if (mappingName == null) continue;

                object? value = property.GetValue(this);
                if (value != null)
                {
                    nodePropertyDic[mappingName] = value;
                }
            }

            var outputPropertys = output?.GetType().GetProperties();
            foreach (var outputProperty in outputPropertys)
            {
                var mappingName = GetMappingName(outputProperty);
                if (mappingName == null) continue;
                if (outputProperty?.CanWrite == true && nodePropertyDic.TryGetValue(mappingName, out var vaule))
                {
                    outputProperty.SetValue(output, vaule);
                }

            }
        }

        // 获取节点的特性标记
        public static string GetMappingName(PropertyInfo property)
        {
            var attribute = property.GetCustomAttribute<NodeTypeAttribute>();
            return attribute?.Name;
        }
    }
}
